package com.woniuxy.project115.kaer.platform.interceptor;

import com.woniuxy.project115.kaer.commons.util.JwtUtil;
import com.woniuxy.project115.kaer.platform.util.RedisKey;
import com.woniuxy.project115.kaer.platform.annotation.RequirePermission;
import com.woniuxy.project115.kaer.platform.annotation.RequireRole;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.List;

@Component
public class PermissionInterceptor implements HandlerInterceptor {
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private RedisTemplate<String, Object> redisObjectTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("进入权限拦截器");
        // 排除 OPTIONS 请求
        if (request.getMethod().equals("OPTIONS")) {
            return true;
        }

        // 如果是静态资源请求，直接放行
        if (handler instanceof ResourceHttpRequestHandler) {
            return true;
        }

        // 检查 handler 是否是 HandlerMethod 类型
        if (!(handler instanceof HandlerMethod)) {
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            response.getWriter().write("无权限访问");
            return false;
        }

        // 从请求头中获取 token
        String token = request.getHeader("token");
        if (token == null || token.isEmpty()) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.getWriter().write("未提供 token");
            return false;
        }

        // 取出长 token（短 token 可能过期）
        String refreshToken = stringRedisTemplate.opsForValue().get(RedisKey.ACCESS_REFRESH(token));
        if (refreshToken == null || refreshToken.isEmpty()) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.getWriter().write("token 无效或已过期");
            return false;
        }

        // 解析 token 获取角色
        String role = JwtUtil.parseToken(refreshToken).get("role").toString();
        System.out.println("当前用户角色: " + role);

        // 获取当前请求方法
        Method method = ((HandlerMethod) handler).getMethod();

        // 检查方法上的 @RequireRole 注解
        if (method.isAnnotationPresent(RequireRole.class)) {
            RequireRole requireRole = method.getAnnotation(RequireRole.class);
            String requireRoleName = requireRole.value();

            if (!role.equals(requireRoleName)) {
                // 检查方法上的 @RequirePermission 注解
                if (method.isAnnotationPresent(RequirePermission.class)) {
                    System.out.println("进入权限资源认证");
                    String requirePermissionName = method.getAnnotation(RequirePermission.class).value();

                    // 获取用户 ID
                    Integer userId = JwtUtil.getUserId(refreshToken);
                    if (userId == null) {
                        System.out.println("用户信息无效");
                        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                        response.getWriter().write("用户信息无效");
                        return false;
                    }

                    // 从 Redis 中获取用户权限列表
                    List<String> permissionList = (List<String>) redisObjectTemplate.opsForValue().get(RedisKey.USER_PERMISSION_LIST(userId));
                    System.out.println(permissionList);
                    if (permissionList == null || !permissionList.contains(requirePermissionName)) {
                        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
                        response.getWriter().write("无权限访问");
                        System.out.println("无权限访问");
                        return false;
                    }
                }
                System.out.println("权限认证通过");
            }
            return true;
        }
        // 通过所有检查，放行请求
        return true;
    }
}